package com.example.demo;

import com.alibaba.druid.filter.Filter;
import com.alibaba.druid.filter.logging.Slf4jLogFilter;
import com.alibaba.druid.filter.stat.StatFilter;
import com.alibaba.druid.pool.DruidDataSource;
import com.alibaba.druid.spring.boot.autoconfigure.DruidDataSourceBuilder;
import com.alibaba.druid.support.http.StatViewServlet;
import org.activiti.spring.boot.SecurityAutoConfiguration;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.domain.EntityScan;
import org.springframework.boot.web.servlet.ServletComponentScan;
import org.springframework.boot.web.servlet.ServletRegistrationBean;
import org.springframework.cloud.openfeign.EnableFeignClients;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Primary;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.transaction.annotation.EnableTransactionManagement;

import javax.sql.DataSource;
import java.util.ArrayList;
import java.util.List;


//@Target(ElementType.TYPE) 注解的使用范围,其中TYPE用于描述类,接口(包括包注解类型)或enum声明
//@Retention(RetentionPolicy.RUNTIME) 注解的声明周期,保留到class文件中(三个生命周期)
//@Documented 表明这个注解应该被javadoc记录
//@Inherited 子类可以继承该注解
//@EnableAutoConfiguration 开启springboot的注解功能,springboot的四大神器之一,其借助@import的帮助
//@EnableScheduling 是通过@Import将Spring调度框架相关的bean定义都加载到IOC容器(定时任务,时间调度任务)
//@EnableMBeanExport 是通过@Import将JMX相关的bean定义加载到IOC容器(监控JVM运行时状态)
@SpringBootApplication(exclude = {SecurityAutoConfiguration.class})//排除activiti自身Sercurity配置类
@EnableTransactionManagement//开启事务管理
@ServletComponentScan("com.example.demo.config")
@EnableJpaRepositories(basePackages = {"com.example.demo.vo"})
@EntityScan(basePackages = {"com.example.demo.vo"})
@EnableAsync //开启异步事件监听
@EnableFeignClients
public class DemoApplication {

    public static void main(String[] args) {
        SpringApplication.run(DemoApplication.class, args);
    }

    /**
     * 配置durid监控页面帐号密码
     *
     * @return
     */
    @Bean
    public ServletRegistrationBean druidStatViewServlet() {
        //先配置管理后台的servlet,访问的入口为/druid/
        ServletRegistrationBean servletRegistrationBean = new ServletRegistrationBean(
                new StatViewServlet(), "/druid/*");
        //Ip白名单(没有配置获取为空,则允许所有访问)
        servletRegistrationBean.addInitParameter("allow", "127.0.0.1");
        //IP黑明单(存在共同时.deny优先于allow)
        servletRegistrationBean.addInitParameter("deny", "");
        servletRegistrationBean.addInitParameter("loginUsername", "admin");
        servletRegistrationBean.addInitParameter("loginPassword", "123456");
        servletRegistrationBean.addInitParameter("resetEnable", "false");
        return servletRegistrationBean;
    }

    @Bean(name = "statFilter")
    public StatFilter statFilter() {
        StatFilter statFilter = new StatFilter();
        //慢sql时间设置,即执行时间大于200毫秒的都是慢sql
        statFilter.setSlowSqlMillis(5);
        statFilter.setLogSlowSql(true);
        statFilter.setMergeSql(true);
        return statFilter;
    }

    @Bean(name = "logFilter")
    public Slf4jLogFilter logFilter() {
        Slf4jLogFilter slf4jLogFilter = new Slf4jLogFilter();
        slf4jLogFilter.setDataSourceLogEnabled(true);
        slf4jLogFilter.setStatementExecutableSqlLogEnable(true);
        return slf4jLogFilter;
    }

    @Bean
    @Primary
    DataSource mainConfig() {
        DruidDataSource druidDataSource = DruidDataSourceBuilder.create().build();
        List<Filter> filters = new ArrayList<>();
        filters.add(statFilter());
        filters.add(logFilter());
        druidDataSource.setProxyFilters(filters);

        return druidDataSource;
    }
}